<?php

namespace App\Http\Controllers\Admin;

use App\Exports\OrderExport;
use App\Http\Controllers\Controller;
use App\Jobs\DeliveryCallbackJob;
use App\Models\Order;
use App\Models\OrderSku;
use App\Services\Order\CancelOrder;
use App\Services\Order\OrderContext;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpKernel\Exception\HttpException;

class OrderController extends Controller
{
    public function list(Request $request)
    {
        if ($request->has('export')) {
            return (new OrderExport($request))->download(sprintf('订单(%s).xls', Carbon::now()->format('YmdHisu')));
        }

        return $this->response->array(
            Order::query()
                ->withoutGlobalScope('orderByIdDesc')
                ->with(['agent'])
                ->when($request->get('numbering'), function (Builder $builder, $numbering) {
                    $builder->where('orders.numbering', $numbering);
                })
                ->when($request->get('commodity_numbering'), function (Builder $builder, $commodityNumbering) {
                    $builder->where('orders.commodity_numbering', $commodityNumbering);
                })
                ->when($request->get('commodity_activity_id'), function (Builder $builder, $commodityActivityId) {
                    $builder->where('orders.commodity_activity_id', $commodityActivityId);
                })
                ->when($request->get('status'), function (Builder $builder, $status) {
                    $builder->where('orders.status', $status);
                })
                ->when($request->get('client_search_name'), function (Builder $builder, $clientSearch) {
                    $builder->where('orders.client_name', 'like', "$clientSearch%");
                })
                ->when($request->get('client_search_phone'), function (Builder $builder, $clientSearch) {
                    $builder->where('orders.client_phone', 'like', "$clientSearch%");
                })
                ->when($request->get('agent_search'), function (Builder $builder, $agentSearch) {
                    $builder
                        ->join('agents', 'agents.id', '=', 'orders.agent_id')
                        ->where(function (Builder $builder) use ($agentSearch) {
                            $builder->when(
                                is_numeric($agentSearch) && mb_strlen($agentSearch) === 11,
                                function (Builder $builder) use ($agentSearch) {
                                    $builder->where('agents.phone', $agentSearch);
                                },
                                function (Builder $builder) use ($agentSearch) {
                                    $builder->where('agents.name', 'like', "$agentSearch%");
                                });
                        });
                })
                ->when($request->get('created_at_begin'), function (Builder $query, $createdAtBegin) {
                    $query->where('orders.order_date', '>=', $createdAtBegin);
                })
                ->when($request->get('created_at_end'), function (Builder $query, $createdAtEnd) {
                    $query->where('orders.order_date', '<=', $createdAtEnd);
                })
                ->when(empty($request->except(['s', 'page', 'per_page'])),
                    function (Builder $query) {
                        $query->orderByDesc('orders.order_date');
                    },
                    function (Builder $query) {
                        $query->orderByDesc('orders.id');
                    })
                ->select(['orders.*'])
                ->paginate()
        );
    }

    public function info($id)
    {
        return $this->response->array(
            Order::query()
                ->with(['agent', 'skus', 'supplier', 'courierInformation.courierCompany', 'afterSaleOrder.afterSaleOrderSkus'])
                ->findOrFail($id)
                ->toArray()
        );
    }

    /**
     * 管理备注
     * @param Request $request
     * @return \Dingo\Api\Http\Response
     */
    public function remark(Request $request)
    {
        try {
            Order::query()
                ->where('id', $request->get('id'))
                ->update([
                    'management_notes' => $request->get('remark', '')
                ]);
        } catch (\Exception $e) {
            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->created(null);
    }

    /**
     * 取消订单
     */
    public function cancelByNumbering($numbering)
    {
        try {
            $order = Order::query()
                ->with([
                    'skus',
                    'commodityActivity' => fn(BelongsTo $belongsTo) => $belongsTo->withTrashed()
                ])
                ->where('numbering', $numbering)
                ->firstOrFail();

            (new OrderContext(new CancelOrder(\Auth::id(), Order::CANCEL_TYPE_ADMIN)))->excuteOperation($order);

            // 回调取消订单通知
            if (!empty($order['delivery_callback'])) {
                dispatch((new DeliveryCallbackJob([
                    'numbering' => $order['numbering'],
                    'delivery_callback' => $order['delivery_callback'],
                    'status' => Order::STATUS_CANCELLED
                ]))->onQueue('delivery_callback'));
            }
        } catch (ModelNotFoundException $e) {
            $this->response->errorBadRequest('订单不存在');
        }

    }

    /**
     * 订单快递
     * @param Request $request
     * @return \Dingo\Api\Http\Response
     */
    public function expressDelivery(Request $request)
    {
        try {
            $order = Order::query()
                ->with(['skus.commodityActivitySku'])
                ->when($request->get('order_id'), function (Builder $builder, $orderId) {
                    $builder->where('id', $orderId);
                })
                ->when($request->get('numbering'), function (Builder $builder, $numbering) {
                    $builder->where('numbering', $numbering);
                })
                ->firstOrFail();
        } catch (ModelNotFoundException $e) {
            $this->response->errorBadRequest('订单不存在');
        }
        if ($order['status'] === Order::STATUS_CANCELLED) {
            throw new HttpException(400, '订单已取消');
        }

        try {
            \DB::beginTransaction();

            $order->courierInformation()->delete();
            $order->courierInformation()->createMany($request->get('courier_information'));

            if ($order['status'] === Order::STATUS_TO_BE_DELIVERED) {
                $order->update(['status' => Order::STATUS_SHIPPED]);
                // 如果有发货回调地址
                if (!empty($order['delivery_callback'])) {
                    dispatch((new DeliveryCallbackJob([
                        'numbering' => $order['numbering'],
                        'delivery_callback' => $order['delivery_callback'],
                        'courier_information' => $order->courierInformation()->with('courierCompany')->get()->toArray(),
                        'status' => Order::STATUS_SHIPPED,
                    ]))->onQueue('delivery_callback'));
                }

                // [统计] SKU 发货量
                $order->skus->each(function ($sku) {
                    /** @var OrderSku $sku */
                    $sku->commodityActivitySku->incrementShipment($sku['amount']);
                });
            }

            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();
            throwHttpError('订单快递处理失败', $e);
        }

        return $this->response->created(null);
    }

    /**
     * 修改订单 收件信息
     */
    public function updateReceivingInformation($id, Request $request)
    {
        $req = $request->only([
//                'client_name', 'client_phone',
            'client_address' // 现只开放地址
        ]);

        validator(
            $request->only([
//                'client_name', 'client_phone',
                'client_address' // 现只开放地址
            ]),
            [
//                'client_name',
//                'client_phone',
                'client_address' => 'required'
            ],
            [
                'client_address.required' => '请填写地址信息'
            ]
        )->validate();

        $order = Order::query()->select(['id'])->findOrFail($id);
        $order->update($req);

        return $this->response->noContent();
    }
}
